package com.olive.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authorization.ReactiveAuthorizationManager;
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.authorization.AuthorizationContext;

@Configuration
public class SecurityConfig {

	@Autowired
	private JwtServerSecurityContextRepository jwtServerSecurityContextRepository;
	
	@Autowired
	private AuthorizationWhiteUrlMatcher authorizationWhiteUrlMatcher;
	
	@Autowired
	private AuthenticationWhiteUrlMatcher authenticationWhiteUrlMatcher;

	@Autowired(required = false)
	private ReactiveAuthorizationManager<AuthorizationContext> reactiveAuthorizationManager;
	
	@Autowired
	private DefaultServerAccessDeniedHandler defaultServerAccessDeniedHandler;
	
	@Autowired
	private CustomAuthenticationManager customAuthenticationManager;

	@Bean
	public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
		// Disable default security. 关闭默认鉴权功能
		http.httpBasic().disable();
		http.formLogin().disable();
		http.csrf().disable();
		http.logout().disable();

		http.exceptionHandling(
				exceptionHandlingSpec -> exceptionHandlingSpec.accessDeniedHandler(defaultServerAccessDeniedHandler));

		// 配置Token提取器
		http.securityContextRepository(jwtServerSecurityContextRepository);
		// 配置认证类
		http.authenticationManager(customAuthenticationManager);

		// 除白名单外，其他全部路径都需要鉴权
		if (reactiveAuthorizationManager != null) {
			http.authorizeExchange().matchers(authorizationWhiteUrlMatcher).permitAll();
			http.authorizeExchange().anyExchange().access(reactiveAuthorizationManager);
		}

		HttpAuthenticationFilter authenticationFilter = new HttpAuthenticationFilter(customAuthenticationManager,
				jwtServerSecurityContextRepository);
		authenticationFilter.setServerAccessDeniedHandler(defaultServerAccessDeniedHandler);
		authenticationFilter.setRequiresAuthenticationMatcher(authenticationWhiteUrlMatcher);
		http.addFilterAt(authenticationFilter, SecurityWebFiltersOrder.AUTHENTICATION);

		return http.build();
	}

}